﻿@page "/html"
@using System.Text.Json
@using AngleSharp
@using TableTools.Handlers
@using TableTools.Models
@using TableTools.Services
@using TableTools.Shared
@rendermode InteractiveServer
@inject IServiceProvider ServiceProvider
@inject ClassHandler ClassHandler
@inject IJSRuntime JS
@inject ILogger<HtmlTable> Logger

<link href="/fontawesome/fontawesome.min.css" rel="stylesheet" />
<script src="/bootstrap/bootstrap.min.js"></script>

<style>
    .setting-flex{
        display: flex;
        justify-content: flex-start;
    }

    .setting-flex-item{
        width: 150px;
        margin: 5px;
    }
    
    .flex-lg-fill{
        max-width: 85vw;
        padding: 5px;
        display: flex;
        justify-content: flex-start;
    }

    .flex-left{
        height: calc(100vh - 240px);
        max-height: calc(100vh - 240px);;
        width: 70%;
        max-width: 70%;
        overflow-y: scroll;
        border-right: 1px solid #eee;
        padding: 5px;
    }

    .flex-right{
        height: calc(100vh - 240px);
        max-height: calc(100vh - 240px);
        width: 30%;
        max-width: 30%;
        overflow-y: scroll;
    }

    .table-box{
        margin: 5px 0px;
        padding: 5px;
    }

    .collapse-show{
        display: flex;
        justify-content: flex-start;
    }
    
    .collapse-show-name{
        max-width: 70%;
        margin-left: 5px;
    }
    
    .collapse-span-index{
        line-height: 36px;
        margin-left: 5px;
        width: 50px;
        display: inline-block;
        text-align: right;
    }

    .collapse-span{
        margin: 0px 5px;
    }
    
    .setting-flex-item-table{
        line-height: 36px;
    }
    
    .checkbox-table{
        margin: 5px;
    }
</style>

<div class="input-group">
    <div class="input-group" style="width: 200px; height: 36px; padding: 0px; margin-right: 5px;">
        <span class="input-group-text" id="field-attribute">文件类型</span>
        <select class="form-select" aria-describedby="field-attribute" @onchange="SelectedFileTypeChanged" value="@((int)settings.FileType)">
            <option value="0">HTML</option>
            <option value="1">Word</option>
            <option value="2">PDF</option>
        </select>
    </div>
    <span class="input-group-text" id="address">地址</span>
    <input id="uri" class="form-control" type="text" @bind-value="settings.UrlOrPath" />
    <button class="btn btn-outline-secondary" style="display: @(settings.FileType == TableFileType.HTML ? "block" : "none");" @onclick="Open">打开</button>
    <button class="btn btn-outline-secondary" @onclick="ToTable">提取</button>
</div>

<div>
    <div class="setting-flex">
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-index">字段名称</span>
            <input type="text" class="form-control" aria-describedby="field-index" @bind-value="settings.Settings.FieldNameIndex"/>
        </div>
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-type">字段类型</span>
            <input type="text" class="form-control" aria-describedby="field-type" @bind-value="settings.Settings.FieldTypeIndex"/>
        </div>
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-desc">字段备注</span>
            <input type="text" class="form-control" aria-describedby="field-desc" @bind-value="settings.Settings.FieldDescIndex"/>
        </div>
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-value">字段值</span>
            <input type="text" class="form-control" aria-describedby="field-value" @bind-value="settings.Settings.FieldValueIndex"/>
        </div>
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-check">字段约束</span>
            <input type="text" class="form-control" aria-describedby="field-check" @bind-value="settings.Settings.FieldCheckIndex"/>
        </div>
        <div class="input-group mb-3 setting-flex-item">
            <span class="input-group-text" id="field-attribute">特性</span>
            <select class="form-select" aria-describedby="field-attribute" @onchange="SelectedFieldAttributeChanged" value="@((int)settings.Settings.Type)">
                <option value="0">无</option>
                <option value="1">Json</option>
                <option value="2">NewJson</option>
                <option value="3">XML</option>
            </select>
        </div>
        <div class="input-group mb-3 setting-flex-item setting-flex-item-table">
            <input id="use-table" type="checkbox" class="check-input checkbox-table" 
                   checked="@settings.Settings.IsUseTable" 
                   @bind-value="settings.Settings.IsUseTable"/>
            <label for="use-table">使用表格</label>
        </div>
        <div class="input-group mb-3 setting-flex-item setting-flex-item-table">
            <input id="internal" type="checkbox" class="check-input checkbox-table"
                   checked="@settings.Settings.IsInternal"
                   @bind-value="settings.Settings.IsInternal"/>
            <label for="internal">内部</label>
        </div>
    </div>
    <div class="input-group">
        <input id="search-value" class="form-control" type="text" @bind-value="searchValue" />
        <button id="search" class="btn btn-outline-secondary" @onclick="ToSearch">搜索</button>
        <button id="all-collapse" class="btn btn-outline-secondary" onclick="toAllCollapse()">一键展开</button>
        <button id="all-collapse" class="btn btn-outline-secondary" onclick="toAllClose()">一键折叠</button>
        @* <button class="btn btn-outline-secondary" @onclick="ToClass">生成类对象</button> *@
    </div>
</div>

<div class="flex-lg-fill">
    <div class="flex-left">
        @if (shouldRender)
        {
            @foreach (var template in result.Tables)
            {
                <div class="table-box" style="border: @(SelectedTable == template ? "2px solid #00BFFF" : "1px dashed #eee");">
                    <div class="collapse-show">
                        <span class="collapse-span-index">@template.Index . </span>
                        <div class="input-group mb-3 collapse-show-name">
                            <span class="input-group-text" id="table-index@(template.Index)">类名</span>
                            <input type="text" class="form-control" aria-describedby="table-index@(template.Index)" @bind-value="template.Name"/>
                        </div>
                        <span class="collapse-span">
                            <button class="btn btn-primary collapse-btn" type="button" data-bs-toggle="collapse"
                                    data-bs-target="#collapse-table-@(template.Index)" aria-expanded="false"
                                    aria-controls="collapse-table-@(template.Index)">
                                展开
                            </button>
                        </span>
                        <span class="collapse-span">
                           @*  <button class="btn btn-danger" type="button" @onclick="(()=>SelectedTableChanged(template))">
                                选择
                            </button> *@
                            <button class="btn btn-outline-secondary" @onclick="(()=>ToClass(template))">生成</button>
                        </span>
                        <span class="collapse-span">
                            <button class="btn btn-danger" type="button" @onclick="(()=>RemovedTable(template))">
                                移除
                            </button>
                        </span>
                    </div>
                    <div class="collapse" id="collapse-table-@(template.Index)">
                        <div class="card card-body">
                            <table class="table table-bordered" style="display : @(settings.Settings.IsUseTable ? "block" : "none");">
                                <thead>
                                    <tr>
                                        @foreach (var th in template.Table.Headers)
                                        {
                                            <th>@th</th>
                                        }
                                    </tr>
                                </thead>
                                <tbody>
                                    @for (var i = 0; i < template.Table.Row; i++)
                                    {
                                        <tr>
                                            @for (var j = 0; j < template.Table.Col; j++)
                                            {
                                                <td>@template.Table.Rows[i][j]</td>
                                            }
                                        </tr>
                                    }
                                </tbody>
                            </table>
                            <code style="display : @(settings.Settings.IsUseTable ? "block" : "none");">
                                @template.JsonCode
                            </code>
                        </div>
                    </div>
                </div>
            }
        }
    </div>
    <div class="flex-right">
        <textarea style="width: 100%; height: 100%">
            @classString
        </textarea>
    </div>
</div>

<script>
    function toAllCollapse() {
        for (var div of document.querySelectorAll(".collapse-show")) {
            toCollapse(div, false);
        }
    }
    function toAllClose() {
        for (var div of document.querySelectorAll(".collapse-show")) {
            toCollapse(div, true);
        }
    }
    function toCollapseByIndex(index) {
        var div = document.querySelectorAll(".collapse-show")[index];
        var btn = div.querySelector(".collapse-btn");
        if (JSON.parse(btn.getAttribute("aria-expanded")) == false) {
            btn.click();
        }
    }
    function toCollapse(div, isOpen) {
        var btn = div.querySelector(".collapse-btn");
        if (JSON.parse(btn.getAttribute("aria-expanded")) == isOpen) {
            btn.click();
        }
    }
</script>

@code {
    private LocalCacheSettings settings = new LocalCacheSettings();

    private TableResult result = new TableResult();

    private string? classString;

    private TableTemplate? SelectedTable;

    protected override bool ShouldRender() => shouldRender;
    private bool shouldRender;

    private bool isLoading = true;

    private ITableService? TableService;

    private string? searchValue;

    protected override void OnInitialized()
    {
        try
        {
            if (File.Exists(LocalCacheSettings.CacheFileName))
            {
                // 读取配置缓存
                var json = File.ReadAllText(LocalCacheSettings.CacheFileName);
                settings = JsonSerializer.Deserialize<LocalCacheSettings>(json);

                TableService = ServiceProvider.GetRequiredKeyedService<ITableService>(settings.FileType.ToString());

                if (File.Exists(TableTemplate.CacheFileName))
                {
                    // 读取数据缓存
                    json = File.ReadAllText(TableTemplate.CacheFileName);
                    result = JsonSerializer.Deserialize<TableResult>(json);
                }
                // Task.Run(async () =>
                // {
                //     await Task.Delay(TimeSpan.FromSeconds(5));
                //     isLoading = false;
                // });
            }

            settings ??= new();
            result ??= new();
        }
        catch (Exception e)
        {
            Logger.LogWarning(e, "加载错误");
        }

        shouldRender = true;
    }

    // private readonly Lazy<IBrowsingContext> browsingContext = new(() =>
    // {
    //     var config = Configuration.Default.WithDefaultLoader();
    //     var context = BrowsingContext.New(config);
    //     return context;
    // });

    private void SelectedFileTypeChanged(ChangeEventArgs e)
    {
        if (e.Value is not null)
        {
            settings.FileType = (TableFileType)int.Parse(e.Value!.ToString()!);

            TableService = ServiceProvider.GetRequiredKeyedService<ITableService>(settings.FileType.ToString());
        }
    }

    private void SelectedFieldAttributeChanged(ChangeEventArgs e)
    {
        if (e.Value is not null)
        {
            settings.Settings.Type = (FieldAttributeType)int.Parse(e.Value!.ToString()!);
        }
    }

    private async Task Open()
    {
        switch (settings.FileType)
        {
            case TableFileType.HTML:
                if (string.IsNullOrWhiteSpace(settings.UrlOrPath))
                {
                    return;
                }

                await ((HtmlToTableService)TableService!).OpenAsync(settings.UrlOrPath);
                break;
            case TableFileType.PDF:
            case TableFileType.Word:

                break;
            default:
                break;
        }
    }

    private async Task ToSearch()
    {
        try
        {
            if (string.IsNullOrWhiteSpace(searchValue))
            {
                throw new ArgumentNullException(nameof(searchValue), "搜索内容不能为空");
            }

            if (shouldRender)
            {
                foreach (var table in result.Tables)
                {
                    if (!string.IsNullOrEmpty(table.Markdown) && table.Markdown.Contains(searchValue))
                    {
                        await JS.InvokeVoidAsync("toCollapseByIndex", table.Index);
                    }
                }
            }
        }
        catch (Exception e)
        {
            Logger.LogWarning(e, "搜索错误");
        }
    }

    private async Task ToTable()
    {
        try
        {
            // var document = await browsingContext.Value.OpenAsync(url);

            // var tables = document.QuerySelectorAll("table");

            // var html = document.ToHtml();

            // Console.WriteLine(document.ToHtml());

            if (string.IsNullOrWhiteSpace(settings.UrlOrPath))
            {
                throw new ArgumentNullException(nameof(settings.UrlOrPath), "输入地址不能为空");
            }

            //isLoading = true;

            result = await TableService!.ToTableAsync(settings.UrlOrPath);

            var json = JsonSerializer.Serialize(result);
            File.WriteAllText(TableTemplate.CacheFileName, json);

            // _ = Task.Run(async () =>
            // {
            //     await Task.Delay(TimeSpan.FromSeconds(5));
            //     isLoading = false;
            // });

            //await JS.InvokeVoidAsync("initDetailData", item);
        }
        catch (Exception e)
        {
            Logger.LogWarning(e, "生成表格错误");
        }
    }

    private void ToClass(TableTemplate template)
    {
        try
        {
            _ = Task.Run(() =>
                {
                    var json = JsonSerializer.Serialize(settings);
                    File.WriteAllText(LocalCacheSettings.CacheFileName, json, System.Text.Encoding.UTF8);
                });
            _ = Task.Run(() =>
                {
                    var json = JsonSerializer.Serialize(result);
                    File.WriteAllText(TableTemplate.CacheFileName, json);
                });

            //SelectedTable ??= result.Tables.First();

            classString = ClassHandler.TableTemplateToClass(new TableToClassRequest()
                {
                    Settings = settings.Settings,
                    Tables = new List<TableTemplate>()
                    {
                        //SelectedTable
                        template
                    }
                });
        }
        catch (Exception e)
        {
            Logger.LogWarning(e, "生成类错误");
        }
    }

    private void SelectedTableChanged(TableTemplate template)
    {
        SelectedTable = template;
    }

    private void RemovedTable(TableTemplate template)
    {
        result.Remove(template);

        _ = Task.Run(() =>
            {
                var json = JsonSerializer.Serialize(result);
                File.WriteAllText(TableTemplate.CacheFileName, json);
            });
    }
}
